﻿using System;
using System.IO;
using System.Text;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Globalization;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Roslyn.Compilers;
using Roslyn.Compilers.CSharp;
using CSCompilation = Roslyn.Compilers.CSharp.Compilation;
using JProgram = PowerLanguages.Compilation.J.Program;

namespace PowerLanguages.Compilation//parser "adapter"
{
    using Microsoft.M;
    using System.Dataflow;
    using MIdentifier = System.Dataflow.Identifier;
    using MParser = System.Dataflow.Parser;

    internal struct Node
    {
        private readonly object _object;
        internal Node(object obj) { _object = obj; }
        internal bool IsNull() { return _object == null; }
        internal bool IsEntity()
        {
            if (IsNull()) return false;
            return _object.GetType() == EntityNodeType;
        }
        internal bool IsCollection()
        {
            if (IsNull()) return false;
            return _object.GetType() == SimpleNodeType;
        }
        internal bool IsList()
        {
            if (IsNull()) return false;
            return _object.GetType() == SequenceNodeType;
        }
        internal bool IsAtom()
        {
            if (IsNull()) return true;
            var type = _object.GetType();
            return type != EntityNodeType && type != SimpleNodeType && type != SequenceNodeType;
        }
        internal string Label()
        {
            if (IsAtom()) throw new InvalidOperationException();
            return ((MIdentifier)GraphBuilderNodeLabelProperty.GetValue(_object, null)).Text;
        }
        internal object AsAtom()
        {
            if (!IsAtom()) throw new InvalidOperationException();
            return _object;
        }
        internal IEnumerable<Node> AsCollection()
        {
            if (!IsCollection()) throw new InvalidOperationException();
            foreach (var obj in (IEnumerable)GraphBuilderNodeSuccessorsProperty.GetValue(_object, null))
                yield return new Node(obj);
        }
        internal IEnumerable<Node> AsList()
        {
            if (!IsList()) throw new InvalidOperationException();
            foreach (var obj in (IEnumerable)SequenceNodeElementsProperty.GetValue(_object, null))
                yield return new Node(obj);
        }
        internal bool HasChild(string childName)
        {
            if (!IsEntity()) throw new InvalidOperationException();
            var members = (IDictionary<object, object>)EntityNodeMembersProperty.GetValue(_object, null);
            return members.ContainsKey(MIdentifier.Get(childName));
        }
        internal Node Child(string childName)
        {
            if (!IsEntity()) throw new InvalidOperationException();
            var members = (IDictionary<object, object>)EntityNodeMembersProperty.GetValue(_object, null);
            return new Node(members[MIdentifier.Get(childName)]);
        }
        internal TextSpanAndLocation GetSpanAndLocation()
        {
            if (IsAtom()) throw new InvalidOperationException();
            return new TextSpanAndLocation(Parser.ToSpan((ISourceLocation)_object), Parser.ToLocation((ISourceLocation)_object));
        }
        internal TextSpan GetSpan()
        {
            if (IsAtom()) throw new InvalidOperationException();
            return Parser.ToSpan((ISourceLocation)_object);
        }
        internal FileLinePositionSpan GetLocation()
        {
            if (IsAtom()) throw new InvalidOperationException();
            return Parser.ToLocation((ISourceLocation)_object);
        }
        private static readonly Type GraphBuilderNodeType;
        private static readonly Type EntityNodeType;
        private static readonly Type SequenceNodeType;
        private static readonly Type SimpleNodeType;
        private static readonly PropertyInfo GraphBuilderNodeLabelProperty;
        private static readonly PropertyInfo GraphBuilderNodeSuccessorsProperty;
        private static readonly PropertyInfo EntityNodeMembersProperty;
        private static readonly PropertyInfo SequenceNodeElementsProperty;
        static Node()
        {
            GraphBuilderNodeType = Type.GetType("System.Dataflow.GraphBuilderNode, System.Dataflow");
            EntityNodeType = Type.GetType("System.Dataflow.EntityNode, System.Dataflow");
            SequenceNodeType = Type.GetType("System.Dataflow.SequenceNode, System.Dataflow");
            SimpleNodeType = Type.GetType("System.Dataflow.SimpleNode, System.Dataflow");
            GraphBuilderNodeLabelProperty = GraphBuilderNodeType.GetProperty("Label", BindingFlags.Public | BindingFlags.Instance);
            GraphBuilderNodeSuccessorsProperty = GraphBuilderNodeType.GetProperty("Successors", BindingFlags.Public | BindingFlags.Instance);
            EntityNodeMembersProperty = EntityNodeType.GetProperty("Members", BindingFlags.Public | BindingFlags.Instance);
            SequenceNodeElementsProperty = SequenceNodeType.GetProperty("Elements", BindingFlags.Public | BindingFlags.Instance);
        }
    }
    internal static class Parser
    {
        internal static Node Parse(CompilationInputItem input, List<Error> errors)
        {
            if (input == null || errors == null) throw new ArgumentNullException();
            var reporter = new Reporter();
            var obj = ParserTable[input.Kind].Parse(new TextReaderTextStream(input.SourceName, input.Source), reporter);
            input.Dispose();
            errors.AddRange(reporter.Errors.Select(i => new Error(input.Kind, CompilationSubKind.Parse, ToLevel(i.Level), ToLocation(i.Location), i.Code, i.ToString()/*.Message*/)));
            return new Node(obj);
        }
        private static readonly Dictionary<CompilationKind, MParser> ParserTable;
        static Parser()
        {
            ParserTable = new Dictionary<CompilationKind, MParser>();
            using (var image = MImage.LoadFromAssembly(Assembly.GetExecutingAssembly()))
            {
                ParserTable.Add(CompilationKind.PowerLanguagesJ, image.ParserFactories["PowerLanguages.JCS"].Create());
            }
        }
        private sealed class Reporter : ErrorReporter
        {
            internal List<ErrorInformation> Errors { get; private set; }
            internal Reporter() { Errors = new List<ErrorInformation>(); }
            protected override void OnError(ErrorInformation errorInformation) { Errors.Add(errorInformation); }
        }
        internal static TextSpan ToSpan(ISourceLocation sourceLocation)
        {
            var start = sourceLocation.Span.Start.Index;
            return new TextSpan(start, sourceLocation.Span.End.Index - start);
        }
        internal static FileLinePositionSpan ToLocation(ISourceLocation sourceLocation)
        {
            return new FileLinePositionSpan(sourceLocation.FileName ?? "", ToLinePosition(sourceLocation.Span.Start), ToLinePosition(sourceLocation.Span.End));
        }
        private static LinePosition ToLinePosition(SourcePoint sourcePoint)
        {
            return new LinePosition(sourcePoint.Line, sourcePoint.Column);
        }
        private static DiagnosticSeverity ToLevel(ErrorLevel level)
        {
            switch (level)
            {
                case ErrorLevel.Error: return DiagnosticSeverity.Error;
                case ErrorLevel.Warning: return DiagnosticSeverity.Warning;
                case ErrorLevel.Message: return DiagnosticSeverity.Info;
                default: throw new ArgumentException();
            }
        }
    }
}

namespace PowerLanguages.Compilation
{
    public enum CompilationKind { None = 0, PowerLanguagesJ = 8 }
    public enum CompilationSubKind { Unspecified = 0, Parse = 1, }
    public sealed class CompilationInput : IDisposable
    {
        public List<CompilationInputItem> Items { get; private set; }
        public CompilationInput(IEnumerable<CompilationInputItem> items = null)
        {
            Items = new List<CompilationInputItem>();
            if (items != null) Items.AddRange(items);
        }
        public void Dispose() { foreach (var i in Items) i.Dispose(); }
        public bool IsValid { get { return Items.Count > 0 && !Items.Any(i => i == null) && !Items.Select(i => i.SourceName).HasDuplicates(StringComparer.InvariantCultureIgnoreCase); } }
    }
    public sealed class CompilationInputItem : IDisposable
    {
        public CompilationKind Kind { get; private set; }
        public string SourceName { get; private set; }//source file full path, identity only. 通常是源文件的全路径，仅作标识，程序不会去dereference
        public TextReader Source { get; private set; }
        public bool AutomaticDisposeSource { get; private set; }
        public CompilationInputItem(CompilationKind kind, string sourceName, TextReader source, bool automaticDisposeSource = true)
        {
            if (kind == CompilationKind.None) throw new ArgumentException("kind");
            if (string.IsNullOrWhiteSpace(sourceName)) throw new ArgumentException("sourceName");
            if (source == null) throw new ArgumentNullException("source");
            Kind = kind;
            SourceName = sourceName;
            Source = source;
            AutomaticDisposeSource = automaticDisposeSource;
        }
        public void Dispose() { if (AutomaticDisposeSource) Source.Dispose(); }
    }
    //temp
    public sealed class CompilationResult
    {
        public JProgram JProgram { get; internal set; }
        public List<Error> Errors { get; internal set; }
        internal CompilationResult() { }
    }
    internal struct ProgramInput
    {
        private readonly Node _node;
        private readonly string _sourceName;
        internal Node Node { get { return _node; } }
        internal string SourceName { get { return _sourceName; } }
        internal ProgramInput(Node node, string sourceName)
        {
            _node = node;
            _sourceName = sourceName;
        }
    }
    public static class Compiler
    {
        [ThreadStatic]
        private static CompilationKind _currentCompilationKind;
        internal static CompilationKind CurrentCompilationKind { get { return _currentCompilationKind; } set { _currentCompilationKind = value; } }
        [ThreadStatic]
        private static CompilationSubKind _currentCompilationSubKind;
        internal static CompilationSubKind CurrentCompilationSubKind { get { return _currentCompilationSubKind; } set { _currentCompilationSubKind = value; } }
        public static CompilationResult Compile(CompilationInput compilationInput)
        {
            if (compilationInput == null || !compilationInput.IsValid) throw new ArgumentException("compilationInput");
            using (compilationInput)
            {
                var compilationResult = new CompilationResult();
                Errors.BeginTrace();
                try
                {
                    foreach (var group in compilationInput.Items.GroupBy(i => i.Kind))
                    {
                        switch (group.Key)
                        {
                            case CompilationKind.PowerLanguagesJ:
                                CurrentCompilationKind = CompilationKind.PowerLanguagesJ;
                                try
                                {
                                    var programInputList = new List<ProgramInput>();
                                    foreach (var inputItem in group)
                                    {
                                        var node = Parser.Parse(inputItem, Errors.CurrentErrorList);
                                        if (node.IsNull()) goto end;
                                        programInputList.Add(new ProgramInput(node, inputItem.SourceName));
                                    }
                                    compilationResult.JProgram = new JProgram(programInputList);
                                }
                                finally { CurrentCompilationKind = CompilationKind.None; }
                                break;
                            default:
                                throw new ArgumentException();
                        }
                    }
                end: ;
                }
                catch (Errors.CompilationException ex)
                {
                    Errors.Report(ex.Error);
                }
                catch (Exception ex)
                {
                    Errors.Report(Errors.CreateError(CompilationKind.None, CompilationSubKind.Unspecified, DiagnosticSeverity.Error, default(FileLinePositionSpan), Errors.InternalCompilerError, ex));
                }
                finally
                {
                    compilationResult.Errors = Errors.EndTrace();
                }
                return compilationResult;
            }
        }
    }
    public sealed class Error
    {
        public CompilationKind Kind { get; private set; }
        public CompilationSubKind SubKind { get; private set; }
        public DiagnosticSeverity Level { get; private set; }
        public FileLinePositionSpan Location { get; private set; }
        public int Code { get; private set; }
        public string Message { get; private set; }
        internal Error(CompilationKind kind, CompilationSubKind subKind, DiagnosticSeverity level, FileLinePositionSpan location, int code, string message)
        {
            Kind = kind;
            SubKind = subKind;
            Level = level;
            Location = location;
            Code = code;
            Message = message;
        }
        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}({1}-{2}): {3}{4} {5}", GetLocationDisplay(Location), Kind, SubKind, Level, Code, Message);
        }
        private static string GetLocationDisplay(FileLinePositionSpan location)
        {
            var fileName = location.FileName;
            try { fileName = Path.GetFileName(fileName); }
            catch (Exception) { }
            return fileName + location.ToString();
        }
    }
    internal static class Errors
    {
        [ThreadStatic]
        private static List<Error> _currentErrorList;
        internal static List<Error> CurrentErrorList
        {
            get
            {
                if (_currentErrorList == null) throw new InvalidOperationException();
                return _currentErrorList;
            }
        }
        internal static void BeginTrace()
        {
            if (_currentErrorList != null) throw new InvalidOperationException();
            _currentErrorList = new List<Error>();
        }
        internal static List<Error> EndTrace()
        {
            var errorList = CurrentErrorList;
            _currentErrorList = null;
            return errorList;
        }
        internal static void Throw(ObjectRoot obj, int code, params object[] args)
        {
            Throw(obj.Location, code, args);
        }
        internal static void Throw(Node node, int code, params object[] args)
        {
            Throw(node.GetLocation(), code, args);
        }
        internal static void Throw(FileLinePositionSpan location, int code, params object[] args)
        {
            throw new CompilationException(CreateError(DiagnosticSeverity.Error, location, code, args));
        }
        internal static void Error(ObjectRoot obj, int code, params object[] args)
        {
            Error(obj.Location, code, args);
        }
        internal static void Error(Node node, int code, params object[] args)
        {
            Error(node.GetLocation(), code, args);
        }
        internal static void Error(FileLinePositionSpan location, int code, params object[] args)
        {
            Report(DiagnosticSeverity.Error, location, code, args);
        }
        internal static void Warning(ObjectRoot obj, int code, params object[] args)
        {
            Warning(obj.Location, code, args);
        }
        internal static void Warning(Node node, int code, params object[] args)
        {
            Warning(node.GetLocation(), code, args);
        }
        internal static void Warning(FileLinePositionSpan location, int code, params object[] args)
        {
            Report(DiagnosticSeverity.Warning, location, code, args);
        }
        internal static void Report(DiagnosticSeverity level, FileLinePositionSpan location, int code, params object[] args)
        {
            Report(CreateError(level, location, code, args));
        }
        internal static void Report(Error error)
        {
            CurrentErrorList.Add(error);
        }
        internal static Error CreateError(DiagnosticSeverity level, FileLinePositionSpan location, int code, params object[] args)
        {
            return CreateError(Compiler.CurrentCompilationKind, Compiler.CurrentCompilationSubKind, level, location, code, args);
        }
        internal static Error CreateError(CompilationKind kind, CompilationSubKind subKind, DiagnosticSeverity level, FileLinePositionSpan location, int code, params object[] args)
        {
            return new Error(kind, subKind, level, location, code, string.Format(CultureInfo.InvariantCulture, MessageTable[code], args));
        }
        internal sealed class CompilationException : Exception
        {
            internal Error Error { get; private set; }
            internal CompilationException(Error error) { Error = error; }
        }
        //
        internal const int BaseStart = 10000;
        internal const int BaseEnd = 19999;
        internal const int JStart = 80000;
        internal const int JEnd = 89999;
        //=============================
        //base error codes
        //=============================
        internal const int InternalCompilerError = BaseStart + 0;
        internal const int InvalidCSharpRightShiftOperatorToken = BaseStart + 1;
        internal const int DuplicateName = BaseStart + 100;

        //=============================
        //J error codes
        //=============================
        internal const int SomeJsonError = JStart + 0;

        private static readonly Dictionary<int, string> MessageTable;
        static Errors()
        {
            MessageTable = new Dictionary<int, string>
            {
                //=============================
                //base error messages
                //=============================
                {InternalCompilerError, "Internal compiler error: {0}"},
                {InvalidCSharpRightShiftOperatorToken, "Invalid C# right shift operator token"},
                {DuplicateName, "Duplicate name '{0}'"},

                //=============================
                //J error messages
                //=============================
                {SomeJsonError, "SomeJsonError"},
            };
        }
    }
    //
    //
    //
    internal static class CSharpUtilities
    {
        internal static bool IsCSharpNode(this Node node) { return node.Label()[0] == '_'; }
        internal static bool IsNotCSharpNode(this Node node) { return !node.IsCSharpNode(); }
        internal static SyntaxNode ToSyntaxNode(this Node node, Func<Node, SyntaxNode, SyntaxNode> extensibleContainerHandler = null)
        {
            if (node.IsNull()) return null;
            SyntaxNode s;
            var nodeLabel = node.Label();
            switch (nodeLabel)
            {
                case "_CompilationUnit":
                    s = Syntax.CompilationUnit(externs: node.Child("Externs").ToSyntaxList<ExternAliasDirectiveSyntax>(), usings: node.Child("Usings").ToSyntaxList<UsingDirectiveSyntax>(),
                    attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(),
                    members: node.Child("Members").ToSyntaxList<MemberDeclarationSyntax>(extensibleContainerHandler));
                    break;
                case "_NamespaceDeclaration":
                    s = Syntax.NamespaceDeclaration(namespaceKeyword: node.Child("NamespaceKeyword").ToSyntaxToken(), name: (NameSyntax)node.Child("Name").ToSyntaxNode(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), externs: node.Child("Externs").ToSyntaxList<ExternAliasDirectiveSyntax>(),
                    usings: node.Child("Usings").ToSyntaxList<UsingDirectiveSyntax>(filterNonCSharpNode: true),
                    members: node.Child("Members").ToSyntaxList<MemberDeclarationSyntax>(extensibleContainerHandler, filterNonCSharpNode: true),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_ExternAliasDirective":
                    s = Syntax.ExternAliasDirective(externKeyword: node.Child("ExternKeyword").ToSyntaxToken(), aliasKeyword: node.Child("AliasKeyword").ToSyntaxToken(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_UsingDirective":
                    s = Syntax.UsingDirective(usingKeyword: node.Child("UsingKeyword").ToSyntaxToken(), aliasOpt: (NameEqualsSyntax)node.Child("AliasOpt").ToSyntaxNode(),
                    name: (NameSyntax)node.Child("Name").ToSyntaxNode(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_AttributeDeclaration":
                    s = Syntax.AttributeDeclaration(openBracketToken: node.Child("OpenBracketToken").ToSyntaxToken(), targetOpt: (AttributeTargetSpecifierSyntax)node.Child("TargetOpt").ToSyntaxNode(),
                    attributes: node.Child("Attributes").ToSeparatedSyntaxList<AttributeSyntax>(), closeBracketToken: node.Child("CloseBracketToken").ToSyntaxToken());
                    break;
                case "_AttributeTargetSpecifier":
                    s = Syntax.AttributeTargetSpecifier(identifier: node.Child("Identifier").ToSyntaxToken(), colonToken: node.Child("ColonToken").ToSyntaxToken());
                    break;
                case "_Attribute":
                    s = Syntax.Attribute(name: (NameSyntax)node.Child("Name").ToSyntaxNode(), argumentListOpt: (AttributeArgumentListSyntax)node.Child("ArgumentListOpt").ToSyntaxNode());
                    break;
                case "_AttributeArgumentList":
                    s = Syntax.AttributeArgumentList(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), arguments: node.Child("Arguments").ToSeparatedSyntaxList<AttributeArgumentSyntax>(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_AttributeArgument":
                    s = Syntax.AttributeArgument(nameEqualsOpt: (NameEqualsSyntax)node.Child("NameEqualsOpt").ToSyntaxNode(), nameColonOpt: (NameColonSyntax)node.Child("NameColonOpt").ToSyntaxNode(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_DelegateDeclaration":
                    s = Syntax.DelegateDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    delegateKeyword: node.Child("DelegateKeyword").ToSyntaxToken(), returnType: (TypeSyntax)node.Child("ReturnType").ToSyntaxNode(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    typeParameterListOpt: (TypeParameterListSyntax)node.Child("TypeParameterListOpt").ToSyntaxNode(), parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    constraintClauses: node.Child("ConstraintClauses").ToSyntaxList<TypeParameterConstraintClauseSyntax>(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_EnumDeclaration":
                    s = Syntax.EnumDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    enumKeyword: node.Child("EnumKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(), baseListOpt: (BaseListSyntax)node.Child("BaseListOpt").ToSyntaxNode(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), members: node.Child("Members").ToSeparatedSyntaxList<EnumMemberDeclarationSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_EnumMemberDeclaration":
                    s = Syntax.EnumMemberDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    equalsValueOpt: (EqualsValueClauseSyntax)node.Child("EqualsValueOpt").ToSyntaxNode());
                    break;
                case "_ClassDeclaration":
                    s = Syntax.ClassDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    keyword: node.Child("ClassKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    typeParameterListOpt: (TypeParameterListSyntax)node.Child("TypeParameterListOpt").ToSyntaxNode(),
                    baseListOpt: (BaseListSyntax)node.Child("BaseListOpt").ToSyntaxNode(), constraintClauses: node.Child("ConstraintClauses").ToSyntaxList<TypeParameterConstraintClauseSyntax>(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), members: node.Child("Members").ToSyntaxList<MemberDeclarationSyntax>(filterNonCSharpNode: true),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_StructDeclaration":
                    s = Syntax.StructDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    keyword: node.Child("StructKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    typeParameterListOpt: (TypeParameterListSyntax)node.Child("TypeParameterListOpt").ToSyntaxNode(),
                    baseListOpt: (BaseListSyntax)node.Child("BaseListOpt").ToSyntaxNode(), constraintClauses: node.Child("ConstraintClauses").ToSyntaxList<TypeParameterConstraintClauseSyntax>(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), members: node.Child("Members").ToSyntaxList<MemberDeclarationSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_InterfaceDeclaration":
                    s = Syntax.InterfaceDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    keyword: node.Child("InterfaceKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    typeParameterListOpt: (TypeParameterListSyntax)node.Child("TypeParameterListOpt").ToSyntaxNode(),
                    baseListOpt: (BaseListSyntax)node.Child("BaseListOpt").ToSyntaxNode(), constraintClauses: node.Child("ConstraintClauses").ToSyntaxList<TypeParameterConstraintClauseSyntax>(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), members: node.Child("Members").ToSyntaxList<MemberDeclarationSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_BaseList":
                    s = Syntax.BaseList(colonToken: node.Child("ColonToken").ToSyntaxToken(), types: node.Child("Types").ToSeparatedSyntaxList<TypeSyntax>());
                    break;
                case "_FieldDeclaration":
                    s = Syntax.FieldDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    declaration: (VariableDeclarationSyntax)node.Child("Declaration").ToSyntaxNode(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_EventFieldDeclaration":
                    s = Syntax.EventFieldDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    eventKeyword: node.Child("EventKeyword").ToSyntaxToken(), declaration: (VariableDeclarationSyntax)node.Child("Declaration").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_MethodDeclaration":
                    s = Syntax.MethodDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    returnType: (TypeSyntax)node.Child("ReturnType").ToSyntaxNode(),
                    explicitInterfaceSpecifierOpt: (ExplicitInterfaceSpecifierSyntax)node.Child("ExplicitInterfaceSpecifierOpt").ToSyntaxNode(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), typeParameterListOpt: (TypeParameterListSyntax)node.Child("TypeParameterListOpt").ToSyntaxNode(),
                    parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(), constraintClauses: node.Child("ConstraintClauses").ToSyntaxList<TypeParameterConstraintClauseSyntax>(),
                    bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_ExplicitInterfaceSpecifier":
                    s = Syntax.ExplicitInterfaceSpecifier(name: (NameSyntax)node.Child("Name").ToSyntaxNode(), dotToken: node.Child("DotToken").ToSyntaxToken());
                    break;
                case "_OperatorDeclaration":
                    s = Syntax.OperatorDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    returnType: (TypeSyntax)node.Child("ReturnType").ToSyntaxNode(), operatorKeyword: node.Child("OperatorKeyword").ToSyntaxToken(),
                    operatorToken: node.Child("OperatorToken").ToSyntaxToken(), parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_ConversionOperatorDeclaration":
                    s = Syntax.ConversionOperatorDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    implicitOrExplicitKeyword: node.Child("ImplicitOrExplicitKeyword").ToSyntaxToken(), operatorKeyword: node.Child("OperatorKeyword").ToSyntaxToken(),
                    type: (TypeSyntax)node.Child("Type").ToSyntaxNode(), parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_ConstructorDeclaration":
                    s = Syntax.ConstructorDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    initializerOpt: (ConstructorInitializerSyntax)node.Child("InitializerOpt").ToSyntaxNode(), bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(),
                    semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_ConstructorInitializer":
                    s = Syntax.ConstructorInitializer(kind: node.Child("Kind").ToSyntaxKind(), colonToken: node.Child("ColonToken").ToSyntaxToken(),
                    thisOrBaseKeyword: node.Child("ThisOrBaseKeyword").ToSyntaxToken(), argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_DestructorDeclaration":
                    s = Syntax.DestructorDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    tildeToken: node.Child("TildeToken").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(), parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(), semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_PropertyDeclaration":
                    s = Syntax.PropertyDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    type: (TypeSyntax)node.Child("Type").ToSyntaxNode(), explicitInterfaceSpecifierOpt: (ExplicitInterfaceSpecifierSyntax)node.Child("ExplicitInterfaceSpecifierOpt").ToSyntaxNode(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), accessorList: (AccessorListSyntax)node.Child("AccessorList").ToSyntaxNode());
                    break;
                case "_IndexerDeclaration":
                    s = Syntax.IndexerDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    type: (TypeSyntax)node.Child("Type").ToSyntaxNode(), explicitInterfaceSpecifierOpt: (ExplicitInterfaceSpecifierSyntax)node.Child("ExplicitInterfaceSpecifierOpt").ToSyntaxNode(),
                    thisKeyword: node.Child("ThisKeyword").ToSyntaxToken(), parameterList: (BracketedParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(),
                    accessorList: (AccessorListSyntax)node.Child("AccessorList").ToSyntaxNode());
                    break;
                case "_AccessorList":
                    s = Syntax.AccessorList(openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), accessors: node.Child("Accessors").ToSyntaxList<AccessorDeclarationSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken());
                    break;
                case "_AccessorDeclaration":
                    s = Syntax.AccessorDeclaration(kind: node.Child("Kind").ToSyntaxKind(), attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(),
                    modifiers: node.Child("Modifiers").ToSyntaxTokenList(), keyword: node.Child("Keyword").ToSyntaxToken(), bodyOpt: (BlockSyntax)node.Child("BodyOpt").ToSyntaxNode(),
                    semicolonTokenOpt: node.Child("SemicolonTokenOpt").ToSyntaxToken());
                    break;
                case "_EventDeclaration":
                    s = Syntax.EventDeclaration(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    eventKeyword: node.Child("EventKeyword").ToSyntaxToken(), type: (TypeSyntax)node.Child("Type").ToSyntaxNode(),
                    explicitInterfaceSpecifierOpt: (ExplicitInterfaceSpecifierSyntax)node.Child("ExplicitInterfaceSpecifierOpt").ToSyntaxNode(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), accessorList: (AccessorListSyntax)node.Child("AccessorList").ToSyntaxNode());
                    break;
                case "_TypeArgumentList":
                    s = Syntax.TypeArgumentList(lessThanToken: node.Child("LessThanToken").ToSyntaxToken(), arguments: node.Child("Arguments").ToSeparatedSyntaxList<TypeSyntax>(),
                    greaterThanToken: node.Child("GreaterThanToken").ToSyntaxToken());
                    break;
                case "_TypeParameterList":
                    s = Syntax.TypeParameterList(lessThanToken: node.Child("LessThanToken").ToSyntaxToken(), parameters: node.Child("Parameters").ToSeparatedSyntaxList<TypeParameterSyntax>(),
                    greaterThanToken: node.Child("GreaterThanToken").ToSyntaxToken());
                    break;
                case "_TypeParameter":
                    s = Syntax.TypeParameter(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), varianceKeywordOpt: node.Child("VarianceKeywordOpt").ToSyntaxToken(),
                    identifier: node.Child("Identifier").ToSyntaxToken());
                    break;
                case "_TypeParameterConstraintClause":
                    s = Syntax.TypeParameterConstraintClause(whereKeyword: node.Child("WhereKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    colonToken: node.Child("ColonToken").ToSyntaxToken(), constraints: node.Child("Constraints").ToSeparatedSyntaxList<TypeParameterConstraintSyntax>());
                    break;
                case "_ConstructorConstraint":
                    s = Syntax.ConstructorConstraint(newKeyword: node.Child("NewKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_TypeConstraint":
                    s = Syntax.TypeConstraint(type: (TypeSyntax)node.Child("Type").ToSyntaxNode());
                    break;
                case "_ClassOrStructConstraint":
                    s = Syntax.ClassOrStructConstraint(kind: node.Child("Kind").ToSyntaxKind(), classOrStructKeyword: node.Child("ClassOrStructKeyword").ToSyntaxToken());
                    break;
                case "_ArgumentList":
                    s = Syntax.ArgumentList(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), arguments: node.Child("Arguments").ToSeparatedSyntaxList<ArgumentSyntax>(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_BracketedArgumentList":
                    s = Syntax.BracketedArgumentList(openBracketToken: node.Child("OpenBracketToken").ToSyntaxToken(), arguments: node.Child("Arguments").ToSeparatedSyntaxList<ArgumentSyntax>(),
                    closeBracketToken: node.Child("CloseBracketToken").ToSyntaxToken());
                    break;
                case "_Argument":
                    s = Syntax.Argument(nameColonOpt: (NameColonSyntax)node.Child("NameColonOpt").ToSyntaxNode(), refOrOutKeywordOpt: node.Child("RefOrOutKeywordOpt").ToSyntaxToken(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_ParameterList":
                    s = Syntax.ParameterList(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), parameters: node.Child("Parameters").ToSeparatedSyntaxList<ParameterSyntax>(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_BracketedParameterList":
                    s = Syntax.BracketedParameterList(openBracketToken: node.Child("OpenBracketToken").ToSyntaxToken(), parameters: node.Child("Parameters").ToSeparatedSyntaxList<ParameterSyntax>(),
                    closeBracketToken: node.Child("CloseBracketToken").ToSyntaxToken());
                    break;
                case "_Parameter":
                    s = Syntax.Parameter(attributes: node.Child("Attributes").ToSyntaxList<AttributeDeclarationSyntax>(), modifiers: node.Child("Modifiers").ToSyntaxTokenList(),
                    typeOpt: (TypeSyntax)node.Child("TypeOpt").ToSyntaxNode(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    defaultOpt: (EqualsValueClauseSyntax)node.Child("DefaultOpt").ToSyntaxNode());
                    break;
                case "_EqualsValueClause":
                    s = Syntax.EqualsValueClause(equalsToken: node.Child("EqualsToken").ToSyntaxToken(), value: (ExpressionSyntax)node.Child("Value").ToSyntaxNode());
                    break;
                case "_NameColon":
                    s = Syntax.NameColon(identifier: node.Child("Identifier").ToSyntaxToken(), colonToken: node.Child("ColonToken").ToSyntaxToken());
                    break;
                case "_NameEquals":
                    s = Syntax.NameEquals(identifier: node.Child("Identifier").ToSyntaxToken(), equalsToken: node.Child("EqualsToken").ToSyntaxToken());
                    break;
                //
                case "_Block":
                    s = Syntax.Block(openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), statements: node.Child("Statements").ToSyntaxList<StatementSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken());
                    break;
                case "_EmptyStatement":
                    s = Syntax.EmptyStatement(semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_ExpressionStatement":
                    s = Syntax.ExpressionStatement(expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_LocalDeclarationStatement":
                    s = Syntax.LocalDeclarationStatement(modifiers: node.Child("Modifiers").ToSyntaxTokenList(), declaration: (VariableDeclarationSyntax)node.Child("Declaration").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_VariableDeclaration":
                    s = Syntax.VariableDeclaration(type: (TypeSyntax)node.Child("Type").ToSyntaxNode(), variables: node.Child("Variables").ToSeparatedSyntaxList<VariableDeclaratorSyntax>());
                    break;
                case "_VariableDeclarator":
                    s = Syntax.VariableDeclarator(identifier: node.Child("Identifier").ToSyntaxToken(), argumentListOpt: (BracketedArgumentListSyntax)node.Child("ArgumentListOpt").ToSyntaxNode(),
                    initializerOpt: (EqualsValueClauseSyntax)node.Child("InitializerOpt").ToSyntaxNode());
                    break;
                case "_LabeledStatement":
                    s = Syntax.LabeledStatement(identifier: node.Child("Identifier").ToSyntaxToken(), colonToken: node.Child("ColonToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_GotoStatement":
                    s = Syntax.GotoStatement(kind: node.Child("Kind").ToSyntaxKind(), gotoKeyword: node.Child("GotoKeyword").ToSyntaxToken(),
                    caseOrDefaultKeywordOpt: node.Child("CaseOrDefaultKeywordOpt").ToSyntaxToken(), expressionOpt: (ExpressionSyntax)node.Child("ExpressionOpt").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_BreakStatement":
                    s = Syntax.BreakStatement(breakKeyword: node.Child("BreakKeyword").ToSyntaxToken(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_ContinueStatement":
                    s = Syntax.ContinueStatement(continueKeyword: node.Child("ContinueKeyword").ToSyntaxToken(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_ReturnStatement":
                    s = Syntax.ReturnStatement(returnKeyword: node.Child("ReturnKeyword").ToSyntaxToken(), expressionOpt: (ExpressionSyntax)node.Child("ExpressionOpt").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_ThrowStatement":
                    s = Syntax.ThrowStatement(throwKeyword: node.Child("ThrowKeyword").ToSyntaxToken(), expressionOpt: (ExpressionSyntax)node.Child("ExpressionOpt").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_YieldStatement":
                    s = Syntax.YieldStatement(kind: node.Child("Kind").ToSyntaxKind(), yieldKeyword: node.Child("YieldKeyword").ToSyntaxToken(),
                    returnOrBreakKeyword: node.Child("ReturnOrBreakKeyword").ToSyntaxToken(), expressionOpt: (ExpressionSyntax)node.Child("ExpressionOpt").ToSyntaxNode(),
                    semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_WhileStatement":
                    s = Syntax.WhileStatement(whileKeyword: node.Child("WhileKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    condition: (ExpressionSyntax)node.Child("Condition").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_DoStatement":
                    s = Syntax.DoStatement(doKeyword: node.Child("DoKeyword").ToSyntaxToken(), statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode(),
                    whileKeyword: node.Child("WhileKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), condition: (ExpressionSyntax)node.Child("Condition").ToSyntaxNode(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(), semicolonToken: node.Child("SemicolonToken").ToSyntaxToken());
                    break;
                case "_ForStatement":
                    s = Syntax.ForStatement(forKeyword: node.Child("ForKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    declarationOpt: (VariableDeclarationSyntax)node.Child("DeclarationOpt").ToSyntaxNode(), initializers: node.Child("Initializers").ToSeparatedSyntaxList<ExpressionSyntax>(),
                    firstSemicolonToken: node.Child("FirstSemicolonToken").ToSyntaxToken(), conditionOpt: (ExpressionSyntax)node.Child("ConditionOpt").ToSyntaxNode(),
                    secondSemicolonToken: node.Child("SecondSemicolonToken").ToSyntaxToken(), incrementors: node.Child("Incrementors").ToSeparatedSyntaxList<ExpressionSyntax>(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(), statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_ForEachStatement":
                    s = Syntax.ForEachStatement(forEachKeyword: node.Child("ForEachKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    type: (TypeSyntax)node.Child("Type").ToSyntaxNode(), identifier: node.Child("Identifier").ToSyntaxToken(), inKeyword: node.Child("InKeyword").ToSyntaxToken(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_UsingStatement":
                    s = Syntax.UsingStatement(usingKeyword: node.Child("UsingKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    declarationOpt: (VariableDeclarationSyntax)node.Child("DeclarationOpt").ToSyntaxNode(), expressionOpt: (ExpressionSyntax)node.Child("ExpressionOpt").ToSyntaxNode(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(), statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_FixedStatement":
                    s = Syntax.FixedStatement(fixedKeyword: node.Child("FixedKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    declaration: (VariableDeclarationSyntax)node.Child("Declaration").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_CheckedStatement":
                    s = Syntax.CheckedStatement(kind: node.Child("Kind").ToSyntaxKind(), checkedOrUncheckedKeyword: node.Child("CheckedOrUncheckedKeyword").ToSyntaxToken(),
                    block: (BlockSyntax)node.Child("Block").ToSyntaxNode());
                    break;
                case "_UnsafeStatement":
                    s = Syntax.UnsafeStatement(unsafeKeyword: node.Child("UnsafeKeyword").ToSyntaxToken(), block: (BlockSyntax)node.Child("Block").ToSyntaxNode());
                    break;
                case "_LockStatement":
                    s = Syntax.LockStatement(lockKeyword: node.Child("LockKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_IfStatement":
                    s = Syntax.IfStatement(ifKeyword: node.Child("IfKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    condition: (ExpressionSyntax)node.Child("Condition").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode(), elseOpt: (ElseClauseSyntax)node.Child("ElseOpt").ToSyntaxNode());
                    break;
                case "_ElseClause":
                    s = Syntax.ElseClause(elseKeyword: node.Child("ElseKeyword").ToSyntaxToken(), statement: (StatementSyntax)node.Child("Statement").ToSyntaxNode());
                    break;
                case "_SwitchStatement":
                    s = Syntax.SwitchStatement(switchKeyword: node.Child("SwitchKeyword").ToSyntaxToken(), openParenToken: node.Child("OpenParenToken").ToSyntaxToken(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(),
                    openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), sections: node.Child("Sections").ToSyntaxList<SwitchSectionSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken());
                    break;
                case "_SwitchSection":
                    s = Syntax.SwitchSection(labels: node.Child("Labels").ToSyntaxList<SwitchLabelSyntax>(), statements: node.Child("Statements").ToSyntaxList<StatementSyntax>());
                    break;
                case "_SwitchLabel":
                    s = Syntax.SwitchLabel(kind: node.Child("Kind").ToSyntaxKind(), caseOrDefaultKeyword: node.Child("CaseOrDefaultKeyword").ToSyntaxToken(),
                    valueOpt: (ExpressionSyntax)node.Child("ValueOpt").ToSyntaxNode(), colonToken: node.Child("ColonToken").ToSyntaxToken());
                    break;
                case "_TryStatement":
                    s = Syntax.TryStatement(tryKeyword: node.Child("TryKeyword").ToSyntaxToken(), block: (BlockSyntax)node.Child("Block").ToSyntaxNode(),
                    catches: node.Child("Catches").ToSyntaxList<CatchClauseSyntax>(), finallyOpt: (FinallyClauseSyntax)node.Child("FinallyOpt").ToSyntaxNode());
                    break;
                case "_CatchClause":
                    s = Syntax.CatchClause(catchKeyword: node.Child("CatchKeyword").ToSyntaxToken(), declarationOpt: (CatchDeclarationSyntax)node.Child("DeclarationOpt").ToSyntaxNode(),
                    block: (BlockSyntax)node.Child("Block").ToSyntaxNode());
                    break;
                case "_CatchDeclaration":
                    s = Syntax.CatchDeclaration(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), type: (TypeSyntax)node.Child("Type").ToSyntaxNode(),
                    identifierOpt: node.Child("IdentifierOpt").ToSyntaxToken(), closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_FinallyClause":
                    s = Syntax.FinallyClause(finallyKeyword: node.Child("FinallyKeyword").ToSyntaxToken(), block: (BlockSyntax)node.Child("Block").ToSyntaxNode());
                    break;
                //
                case "_SimpleLambdaExpression":
                    s = Syntax.SimpleLambdaExpression(parameter: (ParameterSyntax)node.Child("Parameter").ToSyntaxNode(), arrowToken: node.Child("EqualsGreaterThanToken").ToSyntaxToken(),
                    body: node.Child("Body").ToSyntaxNode());
                    break;
                case "_ParenthesizedLambdaExpression":
                    s = Syntax.ParenthesizedLambdaExpression(parameterList: (ParameterListSyntax)node.Child("ParameterList").ToSyntaxNode(), arrowToken: node.Child("EqualsGreaterThanToken").ToSyntaxToken(),
                    body: node.Child("Body").ToSyntaxNode());
                    break;
                case "_BinaryExpression":
                    {
                        var kind = node.Child("Kind").ToSyntaxKind();
                        if (kind == SyntaxKind.RightShiftExpression || kind == SyntaxKind.RightShiftAssignExpression)
                        {
                            var firstNode = node.Child("FirstToken");
                            var secondNode = node.Child("SecondToken");
                            var firstSpanAndLocation = firstNode.GetSpanAndLocation();
                            var secondSpan = secondNode.GetSpan();
                            if (firstSpanAndLocation.Span.End != secondSpan.Start)
                                Errors.Throw(secondNode, Errors.InvalidCSharpRightShiftOperatorToken);
                            firstSpanAndLocation.AddOffset(kind == SyntaxKind.RightShiftExpression ? 1 : 2);
                            s = Syntax.BinaryExpression(kind: kind, left: (ExpressionSyntax)node.Child("Left").ToSyntaxNode(), operatorToken:
                            CreateSyntaxToken(new CSharpSyntaxInfo<SyntaxKind>(kind == SyntaxKind.RightShiftExpression ? SyntaxKind.GreaterThanGreaterThanToken : SyntaxKind.GreaterThanGreaterThanEqualsToken, firstSpanAndLocation)),
                            right: (ExpressionSyntax)node.Child("Right").ToSyntaxNode());
                        }
                        else
                            s = Syntax.BinaryExpression(kind: kind, left: (ExpressionSyntax)node.Child("Left").ToSyntaxNode(), operatorToken: node.Child("OperatorToken").ToSyntaxToken(),
                            right: (ExpressionSyntax)node.Child("Right").ToSyntaxNode());
                    }
                    break;
                case "_ConditionalExpression":
                    s = Syntax.ConditionalExpression(condition: (ExpressionSyntax)node.Child("Condition").ToSyntaxNode(), questionToken: node.Child("QuestionToken").ToSyntaxToken(),
                    whenTrue: (ExpressionSyntax)node.Child("WhenTrue").ToSyntaxNode(), colonToken: node.Child("ColonToken").ToSyntaxToken(),
                    whenFalse: (ExpressionSyntax)node.Child("WhenFalse").ToSyntaxNode());
                    break;
                case "_PrefixUnaryExpression":
                    s = Syntax.PrefixUnaryExpression(kind: node.Child("Kind").ToSyntaxKind(), operatorToken: node.Child("OperatorToken").ToSyntaxToken(),
                    operand: (ExpressionSyntax)node.Child("Operand").ToSyntaxNode());
                    break;
                case "_PostfixUnaryExpression":
                    s = Syntax.PostfixUnaryExpression(kind: node.Child("Kind").ToSyntaxKind(), operand: (ExpressionSyntax)node.Child("Operand").ToSyntaxNode(),
                    operatorToken: node.Child("OperatorToken").ToSyntaxToken());
                    break;
                case "_CastExpression":
                    s = Syntax.CastExpression(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), type: (TypeSyntax)node.Child("Type").ToSyntaxNode(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_ParenthesizedExpression":
                    s = Syntax.ParenthesizedExpression(openParenToken: node.Child("OpenParenToken").ToSyntaxToken(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(),
                    closeParenToken: node.Child("CloseParenToken").ToSyntaxToken());
                    break;
                case "_LiteralExpression":
                    s = Syntax.LiteralExpression(kind: node.Child("Kind").ToSyntaxKind(), token: node.Child("Token").ToSyntaxToken());
                    break;
                case "_ThisExpression":
                    s = Syntax.ThisExpression(token: node.Child("Token").ToSyntaxToken());
                    break;
                case "_BaseExpression":
                    s = Syntax.BaseExpression(token: node.Child("Token").ToSyntaxToken());
                    break;
                case "_TypeOfExpression":
                    s = Syntax.TypeOfExpression(keyword: node.Child("Keyword").ToSyntaxToken(), argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_SizeOfExpression":
                    s = Syntax.SizeOfExpression(keyword: node.Child("Keyword").ToSyntaxToken(), argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_CheckedExpression":
                    s = Syntax.CheckedExpression(kind: node.Child("Kind").ToSyntaxKind(), keyword: node.Child("Keyword").ToSyntaxToken(),
                    argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_DefaultExpression":
                    s = Syntax.DefaultExpression(keyword: node.Child("Keyword").ToSyntaxToken(), argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_MemberAccessExpression":
                    s = Syntax.MemberAccessExpression(kind: node.Child("Kind").ToSyntaxKind(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(),
                    operatorToken: node.Child("OperatorToken").ToSyntaxToken(), name: (SimpleNameSyntax)node.Child("Name").ToSyntaxNode());
                    break;
                case "_ElementAccessExpression":
                    s = Syntax.ElementAccessExpression(expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(),
                    argumentList: (BracketedArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_ArrayCreationExpression":
                    s = Syntax.ArrayCreationExpression(newKeyword: node.Child("NewKeyword").ToSyntaxToken(), type: (ArrayTypeSyntax)node.Child("Type").ToSyntaxNode(),
                    initializerOpt: (InitializerExpressionSyntax)node.Child("InitializerOpt").ToSyntaxNode());
                    break;
                case "_ImplicitArrayCreationExpression":
                    s = Syntax.ImplicitArrayCreationExpression(newKeyword: node.Child("NewKeyword").ToSyntaxToken(), openBracketToken: node.Child("OpenBracketToken").ToSyntaxToken(),
                    commas: node.Child("Commas").ToSyntaxTokenList(), closeBracketToken: node.Child("CloseBracketToken").ToSyntaxToken(),
                    initializer: (InitializerExpressionSyntax)node.Child("Initializer").ToSyntaxNode());
                    break;
                case "_ObjectCreationExpression":
                    s = Syntax.ObjectCreationExpression(newKeyword: node.Child("NewKeyword").ToSyntaxToken(), type: (TypeSyntax)node.Child("Type").ToSyntaxNode(),
                    argumentListOpt: (ArgumentListSyntax)node.Child("ArgumentListOpt").ToSyntaxNode(), initializerOpt: (InitializerExpressionSyntax)node.Child("InitializerOpt").ToSyntaxNode());
                    break;
                case "_AnonymousObjectCreationExpression":
                    s = Syntax.AnonymousObjectCreationExpression(newKeyword: node.Child("NewKeyword").ToSyntaxToken(), initializer: (InitializerExpressionSyntax)node.Child("Initializer").ToSyntaxNode());
                    break;
                case "_InvocationExpression":
                    s = Syntax.InvocationExpression(expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(), argumentList: (ArgumentListSyntax)node.Child("ArgumentList").ToSyntaxNode());
                    break;
                case "_AnonymousMethodExpression":
                    s = Syntax.AnonymousMethodExpression(delegateKeyword: node.Child("DelegateKeyword").ToSyntaxToken(), parameterListOpt: (ParameterListSyntax)node.Child("ParameterListOpt").ToSyntaxNode(),
                    block: (BlockSyntax)node.Child("Block").ToSyntaxNode());
                    break;
                case "_StackAllocArrayCreationExpression":
                    s = Syntax.StackAllocArrayCreationExpression(stackAllocKeyword: node.Child("StackAllocKeyword").ToSyntaxToken(), type: (TypeSyntax)node.Child("Type").ToSyntaxNode());
                    break;
                case "_InitializerExpression":
                    s = Syntax.InitializerExpression(openBraceToken: node.Child("OpenBraceToken").ToSyntaxToken(), expressions: node.Child("Expressions").ToSeparatedSyntaxList<ExpressionSyntax>(),
                    closeBraceToken: node.Child("CloseBraceToken").ToSyntaxToken());
                    break;
                //
                case "_QueryExpression":
                    s = Syntax.QueryExpression(clauses: node.Child("Clauses").ToSyntaxList<QueryClauseSyntax>(), selectOrGroup: (SelectOrGroupClauseSyntax)node.Child("SelectOrGroup").ToSyntaxNode(),
                    continuationOpt: (QueryContinuationSyntax)node.Child("ContinuationOpt").ToSyntaxNode());
                    break;
                case "_FromClause":
                    s = Syntax.FromClause(fromKeyword: node.Child("FromKeyword").ToSyntaxToken(), typeOpt: (TypeSyntax)node.Child("TypeOpt").ToSyntaxNode(),
                    identifier: node.Child("Identifier").ToSyntaxToken(), inKeyword: node.Child("InKeyword").ToSyntaxToken(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_LetClause":
                    s = Syntax.LetClause(letKeyword: node.Child("LetKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(), equalsToken: node.Child("EqualsToken").ToSyntaxToken(),
                    expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_JoinClause":
                    s = Syntax.JoinClause(joinKeyword: node.Child("JoinKeyword").ToSyntaxToken(), typeOpt: (TypeSyntax)node.Child("TypeOpt").ToSyntaxNode(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    inKeyword: node.Child("InKeyword").ToSyntaxToken(), inExpression: (ExpressionSyntax)node.Child("InExpression").ToSyntaxNode(), onKeyword: node.Child("OnKeyword").ToSyntaxToken(),
                    leftExpression: (ExpressionSyntax)node.Child("LeftExpression").ToSyntaxNode(), equalsKeyword: node.Child("EqualsKeyword").ToSyntaxToken(),
                    rightExpression: (ExpressionSyntax)node.Child("RightExpression").ToSyntaxNode(), intoOpt: (JoinIntoClauseSyntax)node.Child("IntoOpt").ToSyntaxNode());
                    break;
                case "_JoinIntoClause":
                    s = Syntax.JoinIntoClause(intoKeyword: node.Child("IntoKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken());
                    break;
                case "_WhereClause":
                    s = Syntax.WhereClause(whereKeyword: node.Child("WhereKeyword").ToSyntaxToken(), condition: (ExpressionSyntax)node.Child("Condition").ToSyntaxNode());
                    break;
                case "_OrderByClause":
                    s = Syntax.OrderByClause(orderByKeyword: node.Child("OrderByKeyword").ToSyntaxToken(), orderings: node.Child("Orderings").ToSeparatedSyntaxList<OrderingSyntax>());
                    break;
                case "_Ordering":
                    s = Syntax.Ordering(kind: node.Child("Kind").ToSyntaxKind(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode(),
                    ascendingOrDescendingKeywordOpt: node.Child("AscendingOrDescendingKeywordOpt").ToSyntaxToken());
                    break;
                case "_SelectClause":
                    s = Syntax.SelectClause(selectKeyword: node.Child("SelectKeyword").ToSyntaxToken(), expression: (ExpressionSyntax)node.Child("Expression").ToSyntaxNode());
                    break;
                case "_GroupClause":
                    s = Syntax.GroupClause(groupKeyword: node.Child("GroupKeyword").ToSyntaxToken(), groupExpression: (ExpressionSyntax)node.Child("GroupExpression").ToSyntaxNode(),
                    byKeyword: node.Child("ByKeyword").ToSyntaxToken(), byExpression: (ExpressionSyntax)node.Child("ByExpression").ToSyntaxNode());
                    break;
                case "_QueryContinuation":
                    s = Syntax.QueryContinuation(intoKeyword: node.Child("IntoKeyword").ToSyntaxToken(), identifier: node.Child("Identifier").ToSyntaxToken(),
                    query: (QueryExpressionSyntax)node.Child("Query").ToSyntaxNode());
                    break;
                //
                case "_ArrayType":
                    s = Syntax.ArrayType(elementType: (TypeSyntax)node.Child("ElementType").ToSyntaxNode(), rankSpecifiers: node.Child("RankSpecifiers").ToSyntaxList<ArrayRankSpecifierSyntax>());
                    break;
                case "_ArrayRankSpecifier":
                    s = Syntax.ArrayRankSpecifier(openBracketToken: node.Child("OpenBracketToken").ToSyntaxToken(), sizes: node.Child("Sizes").ToSeparatedSyntaxList<ExpressionSyntax>(),
                    closeBracketToken: node.Child("CloseBracketToken").ToSyntaxToken());
                    break;
                case "_NullableType":
                    s = Syntax.NullableType(elementType: (TypeSyntax)node.Child("ElementType").ToSyntaxNode(), questionToken: node.Child("QuestionToken").ToSyntaxToken());
                    break;
                case "_PredefinedType":
                    s = Syntax.PredefinedType(keyword: node.Child("Keyword").ToSyntaxToken());
                    break;
                case "_PointerType":
                    s = Syntax.PointerType(elementType: (TypeSyntax)node.Child("ElementType").ToSyntaxNode(), asteriskToken: node.Child("asteriskToken").ToSyntaxToken());
                    break;
                //
                case "_IdentifierName":
                    s = Syntax.IdentifierName(identifier: node.Child("Identifier").ToSyntaxToken());
                    break;
                case "_GenericName":
                    s = Syntax.GenericName(identifier: node.Child("Identifier").ToSyntaxToken(), typeArgumentList: (TypeArgumentListSyntax)node.Child("TypeArgumentList").ToSyntaxNode());
                    break;
                case "_QualifiedName":
                    s = Syntax.QualifiedName(left: (NameSyntax)node.Child("Left").ToSyntaxNode(), dotToken: node.Child("DotToken").ToSyntaxToken(), right: (SimpleNameSyntax)node.Child("Right").ToSyntaxNode());
                    break;
                case "_AliasQualifiedName":
                    s = Syntax.AliasQualifiedName(alias: (IdentifierNameSyntax)node.Child("Alias").ToSyntaxNode(), colonColonToken: node.Child("ColonColonToken").ToSyntaxToken(),
                    name: (SimpleNameSyntax)node.Child("Name").ToSyntaxNode());
                    break;
                default:
                    throw new ArgumentException("node");
            }
            s = AssembleSyntaxNode(s, node.GetSpanAndLocation());
            if (extensibleContainerHandler != null && (s is NamespaceDeclarationSyntax))
                s = extensibleContainerHandler(node, s);
            return s;
        }
        private static SyntaxList<TSyntaxNode> ToSyntaxList<TSyntaxNode>(this Node node, Func<Node, SyntaxNode, SyntaxNode> extensibleContainerHandler = null, bool filterNonCSharpNode = false) where TSyntaxNode : SyntaxNode
        {
            var nodes = node.AsList();
            if (filterNonCSharpNode) nodes = nodes.Where(i => i.IsCSharpNode());
            return Syntax.List<TSyntaxNode>(nodes.Select(i => (TSyntaxNode)i.ToSyntaxNode(extensibleContainerHandler)));
        }
        private static SeparatedSyntaxList<TSyntaxNode> ToSeparatedSyntaxList<TSyntaxNode>(this Node node) where TSyntaxNode : SyntaxNode
        {
            var nodes = node.AsList();
            if (node.Label() == "__")
                return Syntax.SeparatedList<TSyntaxNode>(nodes.Select(i => (SyntaxNodeOrToken)i.ToSyntaxToken()));
            return Syntax.SeparatedList<TSyntaxNode>(nodes.Select(i =>
            {
                if (i.Label() == "_SyntaxToken") return (SyntaxNodeOrToken)i.ToSyntaxToken();
                return (SyntaxNodeOrToken)i.ToSyntaxNode();
            }));
        }
        private static SyntaxTokenList ToSyntaxTokenList(this Node node)
        {
            return Syntax.TokenList(node.AsList().Select(i => i.ToSyntaxToken()));
        }
        private static SyntaxKind ToSyntaxKind(this Node node)
        {
            return node.AsString().ToSyntaxKind();
        }
        private static SyntaxKind ToSyntaxKind(this string value)
        {
            return (SyntaxKind)Enum.Parse(typeof(SyntaxKind), value);
        }
        internal static SyntaxToken ToSyntaxToken(this Node node)
        {
            if (node.IsNull()) return default(SyntaxToken);
            if (node.Label() != "_SyntaxToken") throw new ArgumentException("node");
            var spanAndLocation = node.GetSpanAndLocation();
            SyntaxToken token;
            var kind = node.ChildAsString("Kind");
            switch (kind)
            {
                case "IdentifierToken":
                    token = Syntax.Identifier(node.ChildAsString("Text"));
                    break;
                case "NumericLiteralToken":
                case "CharacterLiteralToken":
                    token = Syntax.ParseToken(node.ChildAsString("Text"));
                    break;
                case "StringLiteralToken":
                    token = Syntax.ParseToken(node.ChildAsString("Text"));
                    if (node.ChildAsBoolean("IsVerbatim"))
                        spanAndLocation.AdjustVerbatimStringLiteralLineCount(token.ValueText);
                    break;
                default:
                    token = Syntax.Token(kind.ToSyntaxKind());
                    break;
                case "$JsonObject":
                    return CreateSyntaxToken(new CSharpSyntaxInfo<SyntaxKind>(SyntaxKind.ClassKeyword, spanAndLocation));
                case "$JsonArray":
                    return CreateSyntaxToken(new CSharpSyntaxInfo<SyntaxKind>(SyntaxKind.ClassKeyword, spanAndLocation));
            }
            return AssembleSyntaxToken(token, spanAndLocation);
        }
        [ThreadStatic]
        private static FileLinePositionSpan? _lastLocation;
        internal static void BeginLocationTrace()
        {
            if (_lastLocation != null) throw new InvalidOperationException();
            _lastLocation = new FileLinePositionSpan("", new LinePosition(1, 1), new LinePosition(1, 1));
        }
        internal static void EndLocationTrace()
        {
            if (_lastLocation == null) throw new InvalidOperationException();
            _lastLocation = null;
        }
        private static SyntaxToken AssembleSyntaxToken(SyntaxToken syntaxToken, TextSpanAndLocation spanAndLocation)
        {
            if (spanAndLocation == null)
                return syntaxToken.WithLeadingTrivia(Syntax.ElasticSpace).WithTrailingTrivia(Syntax.ElasticSpace);
            if (_lastLocation != null)
            {
                var location = spanAndLocation.Location;
                var lastLocation = (FileLinePositionSpan)_lastLocation;
                //Console.WriteLine("token: {0} location:{1} span:{2}", token.ValueText, location, spanAndLocation.Span);
                var triviaList = new List<SyntaxTrivia>();
                var lineCount = location.StartLinePosition.Line - lastLocation.EndLinePosition.Line;
                if (lineCount > 0)
                {
                    triviaList.AddRange(Enumerable.Repeat(Syntax.CarriageReturnLineFeed, lineCount));
                    if (location.StartLinePosition.Character > 1)
                        triviaList.Add(Syntax.Whitespace(new string(' ', location.StartLinePosition.Character - 1), false));
                }
                else if (lineCount == 0)
                {
                    var columCount = location.StartLinePosition.Character - lastLocation.EndLinePosition.Character;
                    if (columCount > 0)
                        triviaList.Add(Syntax.Whitespace(new string(' ', columCount), false));
                    else if (columCount < 0)
                        throw new ArgumentException();
                }
                else
                    throw new ArgumentException();
                _lastLocation = location;
                syntaxToken = syntaxToken.WithLeadingTrivia(triviaList);
            }
            else
                syntaxToken = syntaxToken.WithLeadingTrivia(Syntax.ElasticSpace).WithTrailingTrivia(Syntax.ElasticSpace);
            syntaxToken = syntaxToken.WithTextSpanAndLocation(spanAndLocation);
            return syntaxToken;
        }
        private static SyntaxNode AssembleSyntaxNode(SyntaxNode syntaxNode, TextSpanAndLocation spanAndLocation)
        {
            if (spanAndLocation == null)
                return syntaxNode.WithLeadingTrivia(Syntax.ElasticSpace).WithTrailingTrivia(Syntax.ElasticSpace);
            return syntaxNode.WithTextSpanAndLocation(spanAndLocation);
        }
        internal static SyntaxToken WithTextSpanAndLocation(this SyntaxToken syntaxToken, TextSpanAndLocation spanAndLocation)
        {
            if (spanAndLocation == null) return syntaxToken;
            return syntaxToken.WithAdditionalAnnotations(new TextSpanAndLocationSyntaxAnnotation(spanAndLocation));
        }
        internal static SyntaxNode WithTextSpanAndLocation(this SyntaxNode syntaxNode, TextSpanAndLocation spanAndLocation)
        {
            if (spanAndLocation == null) return syntaxNode;
            return syntaxNode.WithAdditionalAnnotations(new TextSpanAndLocationSyntaxAnnotation(spanAndLocation));
        }
        internal static TextSpanAndLocation GetTextSpanAndLocation(this SyntaxToken syntaxToken)//Roslyn当前版本对SyntaxAnnotation支持不佳, todo
        {
            return null;
        }
        internal static TextSpanAndLocation GetTextSpanAndLocation(this SyntaxNode syntaxNode)//todo
        {
            return null;
        }
        //
        internal static SyntaxToken CreateSyntaxToken(CSharpSyntaxInfo<SyntaxKind> kind)
        {
            return AssembleSyntaxToken(Syntax.Token(kind.Value), kind.SpanAndLocation);
        }
        internal static SyntaxToken CreateIdentifierSyntaxToken(CSharpSyntaxInfo<string> text)
        {
            return AssembleSyntaxToken(Syntax.Identifier(text.Value), text.SpanAndLocation);
        }
        internal static TypeSyntax CreateTypeSyntax(CSharpSyntaxInfo<string> text)
        {
            return (TypeSyntax)AssembleSyntaxNode(Syntax.ParseTypeName(text.Value), text.SpanAndLocation);
        }
        internal static NameSyntax CreateNameSyntax(CSharpSyntaxInfo<string> text)
        {
            return (NameSyntax)AssembleSyntaxNode(Syntax.ParseName(text.Value), text.SpanAndLocation);
        }
        internal static IdentifierNameSyntax CreateIdentifierNameSyntax(CSharpSyntaxInfo<string> text)
        {
            return (IdentifierNameSyntax)AssembleSyntaxNode(Syntax.IdentifierName(text.Value), text.SpanAndLocation);
        }
        internal static SyntaxList<TNode> CreateSyntaxList<TNode>(IEnumerable<TNode> nodes = null) where TNode : SyntaxNode
        {
            if (nodes == null) return default(SyntaxList<TNode>);
            return Syntax.List(nodes);
        }
        internal static SyntaxTokenList CreateModifiersSyntaxTokenList(CSharpModifiers modifiers)
        {
            var tokens = new List<SyntaxToken>();
            if ((modifiers & CSharpModifiers.Private) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.PrivateKeyword));
            if ((modifiers & CSharpModifiers.Protected) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.ProtectedKeyword));
            if ((modifiers & CSharpModifiers.Internal) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.InternalKeyword));
            if ((modifiers & CSharpModifiers.Public) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.PublicKeyword));
            if ((modifiers & CSharpModifiers.Abstract) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.AbstractKeyword));
            if ((modifiers & CSharpModifiers.Sealed) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.SealedKeyword));
            if ((modifiers & CSharpModifiers.Static) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.StaticKeyword));
            if ((modifiers & CSharpModifiers.Ref) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.RefKeyword));
            if ((modifiers & CSharpModifiers.Out) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.OutKeyword));
            if ((modifiers & CSharpModifiers.This) != 0) tokens.Add(CreateSyntaxToken(SyntaxKind.ThisKeyword));
            return Syntax.TokenList(tokens);
        }
        internal static CompilationUnitSyntax CreateCompilationUnitSyntax(IEnumerable<UsingDirectiveSyntax> usings = null, IEnumerable<MemberDeclarationSyntax> members = null,
            IEnumerable<AttributeDeclarationSyntax> attributes = null, IEnumerable<ExternAliasDirectiveSyntax> externs = null)
        {
            return Syntax.CompilationUnit(externs: CreateSyntaxList(externs), usings: CreateSyntaxList(usings), attributes: CreateSyntaxList(attributes), members: CreateSyntaxList(members));
        }
        internal static NamespaceDeclarationSyntax CreateNamespaceDeclarationSyntax(CSharpSyntaxInfo<string> name, IEnumerable<UsingDirectiveSyntax> usings = null,
            IEnumerable<MemberDeclarationSyntax> members = null, IEnumerable<ExternAliasDirectiveSyntax> externs = null)
        {
            return Syntax.NamespaceDeclaration(name: CreateNameSyntax(name), externs: CreateSyntaxList(externs), usings: CreateSyntaxList(usings), members: CreateSyntaxList(members));
        }
        internal static PropertyDeclarationSyntax CreatePropertyDeclarationSyntax(SyntaxTokenList modifiers, CSharpSyntaxInfo<string> type, CSharpSyntaxInfo<string> name,
            BlockSyntax getAccessorBody = null, bool hasSetAccessor = true, BlockSyntax setAccessorBody = null, SyntaxTokenList setAccessorModifiers = default(SyntaxTokenList))
        {
            return Syntax.PropertyDeclaration(modifiers: modifiers, type: CreateTypeSyntax(type), identifier: CreateIdentifierSyntaxToken(name),
            accessorList: CreateAccessorListSyntax(first: CreatePropertyAccessorDeclarationSyntax(body: getAccessorBody),
            second: hasSetAccessor ? CreatePropertyAccessorDeclarationSyntax(false, setAccessorModifiers, setAccessorBody) : null));
        }
        internal static AccessorListSyntax CreateAccessorListSyntax(AccessorDeclarationSyntax first, AccessorDeclarationSyntax second = null)
        {
            if (second == null)
                return Syntax.AccessorList(accessors: Syntax.List(first));
            return Syntax.AccessorList(accessors: Syntax.List(first, second));
        }
        internal static AccessorDeclarationSyntax CreatePropertyAccessorDeclarationSyntax(bool getAccessor = true, SyntaxTokenList modifiers = default(SyntaxTokenList), BlockSyntax body = null)
        {
            return Syntax.AccessorDeclaration(getAccessor ? SyntaxKind.GetAccessorDeclaration : SyntaxKind.SetAccessorDeclaration, modifiers: modifiers,
            bodyOpt: body, semicolonTokenOpt: body != null ? default(SyntaxToken) : SemicolonToken);
        }
        internal static FieldDeclarationSyntax CreateFieldDeclarationSyntax(SyntaxTokenList modifiers, CSharpSyntaxInfo<string> type, CSharpSyntaxInfo<string> name)
        {
            return Syntax.FieldDeclaration(modifiers: modifiers, declaration: Syntax.VariableDeclaration(type: CreateTypeSyntax(type), variables: Syntax.SeparatedList(
                Syntax.VariableDeclarator(identifier: CreateIdentifierSyntaxToken(name)))));
        }
        internal static SyntaxToken SemicolonToken { get { return CreateSyntaxToken(SyntaxKind.SemicolonToken); } }
        internal static SyntaxToken OpenBraceToken { get { return CreateSyntaxToken(SyntaxKind.OpenBraceToken); } }
        internal static SyntaxToken CloseBraceToken { get { return CreateSyntaxToken(SyntaxKind.CloseBraceToken); } }
        internal static SyntaxTokenList PublicModifier { get { return CreateModifiersSyntaxTokenList(CSharpModifiers.Public); } }
        internal static SyntaxTokenList ProtectedModifier { get { return CreateModifiersSyntaxTokenList(CSharpModifiers.Protected); } }
        internal static SyntaxTokenList InternalModifier { get { return CreateModifiersSyntaxTokenList(CSharpModifiers.Internal); } }
        internal static SyntaxTokenList PrivateModifier { get { return CreateModifiersSyntaxTokenList(CSharpModifiers.Private); } }
        //
        //
        internal static string GetNamespaceDeclarationFullName(NamespaceDeclarationSyntax namespaceDeclaration, bool includeGlobalPrefix = true)
        {
            string fullName = null;
            foreach (var nd in namespaceDeclaration.AncestorsAndSelf().OfType<NamespaceDeclarationSyntax>())
            {
                var name = nd.Name.GetText();
                if (fullName == null)
                    fullName = name;
                else
                    fullName = name + "." + fullName;
            }
            if (!includeGlobalPrefix)
                return fullName;
            return "global::" + fullName;
        }
        internal static string StripGlobalPrefix(this string qName)
        {
            return qName.Substring(8);
        }
    }
    internal struct CSharpSyntaxInfo<T>
    {
        private readonly T _value;
        private readonly TextSpanAndLocation _spanAndLocation;
        internal T Value { get { return _value; } }
        internal TextSpanAndLocation SpanAndLocation { get { return _spanAndLocation; } }
        internal CSharpSyntaxInfo(T value, TextSpanAndLocation spanAndLocation = null)
        {
            _value = value;
            _spanAndLocation = spanAndLocation;
        }
        public static implicit operator CSharpSyntaxInfo<T>(T value) { return new CSharpSyntaxInfo<T>(value); }
    }
    [Flags]
    internal enum CSharpModifiers
    {
        None = 0,
        Private = 0x0001,
        Protected = 0x0002,
        Internal = 0x0004,
        Public = 0x0008,
        Abstract = 0x0010,
        Sealed = 0x0020,
        Static = 0x0040,
        Ref = 0x1000,
        Out = 0x2000,
        This = 0x4000,
    }
    //
    public sealed class TextSpanAndLocation
    {
        private TextSpan _span;
        private FileLinePositionSpan _location;
        public TextSpan Span { get { return _span; } }
        public FileLinePositionSpan Location { get { return _location; } }
        internal TextSpanAndLocation(TextSpan span, FileLinePositionSpan location)
        {
            _span = span;
            _location = location;
        }
        //M的bug,"\r\n"会被认为跳了两行，应该跳一行
        internal void AdjustVerbatimStringLiteralLineCount(string text)
        {
            if (text == null) throw new ArgumentNullException("text");
            if (text.Length > 1)
            {
                var crLfCount = 0;
                var index = 0;
                while (index != -1)
                {
                    index = text.IndexOf("\r\n", index);
                    if (index != -1)
                    {
                        crLfCount++;
                        index += 2;
                    }
                }
                if (crLfCount > 0)
                    _location = new FileLinePositionSpan(_location.FileName, _location.StartLinePosition, new LinePosition(_location.EndLinePosition.Line - crLfCount, _location.EndLinePosition.Character));
            }
        }
        internal void AddOffset(int offset)
        {
            if (offset <= 0) throw new ArgumentException("offset");
            _span = new TextSpan(_span.Start, _span.Length + offset);
            _location = new FileLinePositionSpan(_location.FileName, _location.StartLinePosition, new LinePosition(_location.EndLinePosition.Line, _location.EndLinePosition.Character + offset));
        }
    }
    internal sealed class TextSpanAndLocationSyntaxAnnotation : SyntaxAnnotation
    {
        internal TextSpanAndLocation SpanAndLocation { get; private set; }
        internal TextSpanAndLocationSyntaxAnnotation(TextSpanAndLocation spanAndLocation)
        {
            if (spanAndLocation == null) throw new ArgumentNullException("spanAndLocation");
            SpanAndLocation = spanAndLocation;
        }
        internal TextSpanAndLocationSyntaxAnnotation(Node node) : this(node.GetSpanAndLocation()) { }
    }
    //
    //
    //
    public abstract class ObjectRoot
    {
        public TextSpanAndLocation SpanAndLocation { get; private set; }
        public TextSpan Span { get { return SpanAndLocation != null ? SpanAndLocation.Span : default(TextSpan); } }
        public FileLinePositionSpan Location { get { return SpanAndLocation != null ? SpanAndLocation.Location : default(FileLinePositionSpan); } }
        internal ObjectRoot(TextSpanAndLocation spanAndLocation = null) { SpanAndLocation = spanAndLocation; }
        internal virtual void Accept(Node node) { SpanAndLocation = node.GetSpanAndLocation(); }
    }
    public abstract class ValueObject<T> : ObjectRoot, IEquatable<ValueObject<T>>
    {
        public T Value { get; private set; }
        private IEqualityComparer<T> _comparer;
        public IEqualityComparer<T> Comparer
        {
            get { return _comparer; }
            private set
            {
                if (value == null) value = EqualityComparer<T>.Default;
                _comparer = value;
            }
        }
        public static explicit operator T(ValueObject<T> objectValue)
        {
            if (objectValue == null) return default(T);
            return objectValue.Value;
        }
        internal ValueObject(IEqualityComparer<T> comparer = null) { Comparer = comparer; }
        internal ValueObject(Node node, IEqualityComparer<T> comparer = null) { Comparer = comparer; Accept(node); }
        internal ValueObject(T value, IEqualityComparer<T> comparer = null, TextSpanAndLocation spanAndLocation = null)
            : base(spanAndLocation)
        {
            if (value == null) throw new ArgumentNullException("value");
            Value = value;
            Comparer = comparer;
        }
        internal override sealed void Accept(Node node)
        {
            base.Accept(node);
            if (node.IsNull()) throw new ArgumentException();
            object value;
            if (node.IsCollection())
                value = node.AsCollectionSingletonAtom();
            else
                value = node.ToSyntaxToken().Value;
            if (value == null) throw new InvalidOperationException();
            Value = Convert(value);
            if (Value == null) throw new InvalidOperationException();
        }
        internal virtual T Convert(object value) { return (T)value; }
        public bool Equals(ValueObject<T> other) { return !object.ReferenceEquals(other, null) && Comparer.Equals(Value, other.Value); }
        public override sealed bool Equals(object obj) { return Equals(obj as ValueObject<T>); }
        public override sealed int GetHashCode() { return Comparer.GetHashCode(Value); }
        public static bool operator ==(ValueObject<T> left, ValueObject<T> right)
        {
            if (object.ReferenceEquals(left, null))
                return object.ReferenceEquals(right, null);
            return left.Equals(right);
        }
        public static bool operator !=(ValueObject<T> left, ValueObject<T> right) { return !(left == right); }
        public override sealed string ToString() { return Value.ToString(); }
    }
    public sealed class Identifier : ValueObject<string>
    {
        internal Identifier(Node node) : base(node, IdentifierEqualityComparer.Default) { }
        internal Identifier(string value, TextSpanAndLocation spanAndLocation = null) : base(value, IdentifierEqualityComparer.Default, spanAndLocation) { }
        internal SyntaxToken CreateSyntaxToken() { return CSharpUtilities.CreateIdentifierSyntaxToken(new CSharpSyntaxInfo<string>(Value, SpanAndLocation)); }
        internal static bool Equals(string x, string y) { return GetNetValue(x) == GetNetValue(y); }
        internal static string GetNetValue(string value) { return value[0] == '@' ? value.Substring(1) : value; }
    }
    internal sealed class IdentifierEqualityComparer : IEqualityComparer<string>
    {
        internal static readonly IEqualityComparer<string> Default = new IdentifierEqualityComparer();
        bool IEqualityComparer<string>.Equals(string x, string y) { return Identifier.Equals(x, y); }
        int IEqualityComparer<string>.GetHashCode(string obj) { return Identifier.GetNetValue(obj).GetHashCode(); }
        private IdentifierEqualityComparer() { }
    }
    //
    //
    //
    internal static class Extensions
    {
        internal static bool IsNotNull(this Node node) { return !node.IsNull(); }
        internal static string AsString(this Node node) { return (string)node.AsAtom(); }
        internal static int AsInt32(this Node node) { return (int)node.AsAtom(); }
        internal static uint AsUInt32(this Node node) { return (uint)node.AsAtom(); }
        internal static long AsInt64(this Node node) { return (long)node.AsAtom(); }
        internal static ulong AsUInt64(this Node node) { return (ulong)node.AsAtom(); }
        internal static bool AsBoolean(this Node node) { return (bool)node.AsAtom(); }
        internal static Node AsCollectionSingleton(this Node node) { return node.AsCollection().Single(); }
        internal static object AsCollectionSingletonAtom(this Node node) { return node.AsCollectionSingleton().AsAtom(); }
        internal static object ChildAsAtom(this Node node, string childName) { return node.Child(childName).AsAtom(); }
        internal static string ChildAsString(this Node node, string childName) { return node.Child(childName).AsString(); }
        internal static bool ChildAsBoolean(this Node node, string childName) { return node.Child(childName).AsBoolean(); }
        internal static IEnumerable<Node> ChildAsList(this Node node, string childName) { return node.Child(childName).AsList(); }
        //
        internal static string AppendSuffixName(this string path, string suffixName)
        {
            try
            {
                var file = Path.GetFileNameWithoutExtension(path);
                var ext = Path.GetExtension(path);
                var dir = Path.GetDirectoryName(path);
                return Path.Combine(dir, file + suffixName + ext);
            }
            catch (Exception) { return path + suffixName; }
        }
        internal static bool HasDuplicates<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer = null)
        {
            if (source == null) throw new ArgumentNullException("source");
            var set = new HashSet<TSource>(comparer);
            foreach (var i in source)
                if (!set.Add(i))
                    return true;
            return false;
        }
    }

    public abstract class KeyedCollection<TKey, TItem> : Collection<TItem>
        where TKey : ObjectRoot
        where TItem : ObjectRoot
    {
        private readonly IEqualityComparer<TKey> _comparer;
        internal KeyedCollection(IEqualityComparer<TKey> comparer = null)
        {
            if (comparer == null) comparer = EqualityComparer<TKey>.Default;
            _comparer = comparer;
        }
        internal abstract TKey GetKeyForItem(TItem item);
        internal int IndexOfByKey(TKey key)
        {
            if (key == null) throw new ArgumentNullException("key");
            for (int i = 0; i < Count; ++i)
                if (_comparer.Equals(key, GetKeyForItem(Items[i])))
                    return i;
            return -1;
        }
        internal bool TryGetItem(TKey key, out TItem item)
        {
            int index = IndexOfByKey(key);
            if (index == -1)
            {
                item = default(TItem);
                return false;
            }
            item = Items[index];
            return true;
        }
        internal bool ContainsKey(TKey key) { return IndexOfByKey(key) != -1; }
        internal bool RemoveByKey(TKey key)
        {
            int index = IndexOfByKey(key);
            if (index == -1) return false;
            RemoveAt(index);
            return true;
        }
        internal TItem this[TKey key]
        {
            get
            {
                int index = IndexOfByKey(key);
                if (index == -1) throw new KeyNotFoundException("The given key was not present in the collection.");
                return Items[index];
            }
        }
        internal void ThrowIfContains(TItem item)
        {
            TKey key = GetKeyForItem(item);
            if (ContainsKey(key)) Errors.Throw(key, Errors.DuplicateName, key);
        }
        internal void AddOrThrow(TItem item)
        {
            ThrowIfContains(item);
            Add(item);
        }
        internal void AddRange(IEnumerable<TItem> items)
        {
            if (items == null) throw new ArgumentNullException("items");
            foreach (var item in items) Add(item);
        }
        private void CheckDuplicateKey(TItem item)
        {
            if (ContainsKey(GetKeyForItem(item))) throw new ArgumentException("An item with the same key has already been added.");
        }
        protected override sealed void InsertItem(int index, TItem item)
        {
            CheckDuplicateKey(item);
            base.InsertItem(index, item);
        }
        protected override sealed void SetItem(int index, TItem item)
        {
            CheckDuplicateKey(item);
            base.SetItem(index, item);
        }
        internal ReadOnly AsReadOnly() { return new ReadOnly(this); }
        public sealed class ReadOnly : ReadOnlyCollection<TItem>
        {
            private readonly KeyedCollection<TKey, TItem> _parent;
            internal ReadOnly(KeyedCollection<TKey, TItem> parent) : base(parent.Items) { _parent = parent; }
            public int IndexOfByKey(TKey key) { return _parent.IndexOfByKey(key); }
            public bool TryGetItem(TKey key, out TItem item) { return _parent.TryGetItem(key, out item); }
            public bool ContainsKey(TKey key) { return _parent.ContainsKey(key); }
            public TItem this[TKey key] { get { return _parent[key]; } }
        }
    }
}
namespace PowerLanguages.Compilation.J
{
    public abstract class Object : ObjectRoot
    {
        public Object Parent { get; private set; }
        internal Object(Object parent = null) { Parent = parent; }
        internal virtual void Resolve() { }
        internal virtual void Analyze() { }
        internal virtual void Generate() { }
    }
    public sealed class Program : Object
    {
        internal List<CompilationUnit> CompilationUnitList { get; private set; }
        public ReadOnlyCollection<CompilationUnit> CompilationUnits { get { return CompilationUnitList.AsReadOnly(); } }
        public IEnumerable<SyntaxTree> SyntaxTrees
        {
            get
            {
                foreach (var compilationUnit in CompilationUnitList)
                {
                    yield return compilationUnit.OriginalSyntaxTree;
                    if (compilationUnit.GeneratedSyntaxTreeOpt != null)
                        yield return compilationUnit.GeneratedSyntaxTreeOpt;
                }
            }
        }
        internal Program(IEnumerable<ProgramInput> programInputs)
        {
            CompilationUnitList = new List<CompilationUnit>();
            foreach (var programInput in programInputs)
                CompilationUnitList.Add(new CompilationUnit(this, programInput));
            Resolve();
            Analyze();
            Generate();
        }
        internal override void Resolve()
        {
            base.Resolve();
            foreach (var i in CompilationUnitList) i.Resolve();
        }
        internal override void Analyze()
        {
            base.Analyze();
            foreach (var i in CompilationUnitList) i.Analyze();
        }
        internal override void Generate()
        {
            base.Generate();
            foreach (var i in CompilationUnitList) i.Generate();
        }
    }
    public sealed class CompilationUnit : Object
    {
        internal List<Namespace> NamespaceList { get; private set; }
        public ReadOnlyCollection<Namespace> Namespaces { get { return NamespaceList.AsReadOnly(); } }
        public SyntaxTree OriginalSyntaxTree { get; private set; }
        public SyntaxTree GeneratedSyntaxTreeOpt { get; private set; }
        public CompilationUnitSyntax OriginalCompilationUnit { get { return (CompilationUnitSyntax)OriginalSyntaxTree.Root; } }
        public CompilationUnitSyntax GeneratedCompilationUnitOpt { get { return GeneratedSyntaxTreeOpt == null ? null : (CompilationUnitSyntax)GeneratedSyntaxTreeOpt.Root; } }
        public Program ParentProgram { get { return (Program)Parent; } }
        private readonly string _sourceName;
        internal CompilationUnit(Program parent, ProgramInput programInput)
            : base(parent)
        {
            NamespaceList = new List<Namespace>();
            _sourceName = programInput.SourceName;
            Accept(programInput.Node);
        }
        private sealed class NodeSyntaxAnnotation : SyntaxAnnotation
        {
            internal Node Node { get; private set; }
            internal NodeSyntaxAnnotation(Node node) { Node = node; }
        }
        private List<NodeSyntaxAnnotation> _namespaceAnnotationList = new List<NodeSyntaxAnnotation>();
        internal override void Accept(Node compilationUnitNode)
        {
            base.Accept(compilationUnitNode);
            var originalCompilationUnit = (CompilationUnitSyntax)compilationUnitNode.ToSyntaxNode((Node node, SyntaxNode syntaxNode) =>
            {
                var namespaceDeclaration = syntaxNode as NamespaceDeclarationSyntax;
                if (namespaceDeclaration != null)
                    if (node.ChildAsList("Members").Any(i => i.IsNotCSharpNode()))
                    {
                        var annotation = new NodeSyntaxAnnotation(node);
                        syntaxNode = syntaxNode.WithAdditionalAnnotations(annotation);
                        _namespaceAnnotationList.Add(annotation);
                    }
                return syntaxNode;
            });
            OriginalSyntaxTree = SyntaxTree.Create(_sourceName, originalCompilationUnit);
            foreach (var annotation in _namespaceAnnotationList)
            {
                var namespaceDeclaration = (NamespaceDeclarationSyntax)originalCompilationUnit.GetAnnotatedNodesAndTokens(annotation).Single().AsNode();
                var @namespace = new Namespace(this, annotation.Node, namespaceDeclaration);
                NamespaceList.Add(@namespace);
            }
        }
        internal override void Resolve()
        {
            base.Resolve();
            foreach (var i in NamespaceList) i.Resolve();
        }
        internal override void Analyze()
        {
            base.Analyze();
            foreach (var i in NamespaceList) i.Analyze();
        }
        internal override void Generate()
        {
            base.Generate();
            if (NamespaceList.Count > 0)
            {
                var namespaces = NamespaceList.Select(i => { i.Generate(); return i.GeneratedNamespaceDeclaration; });
                var generatedCompilationUnit = CSharpUtilities.CreateCompilationUnitSyntax(usings: OriginalCompilationUnit.Usings, members: namespaces, attributes: OriginalCompilationUnit.Attributes,
                externs: OriginalCompilationUnit.Externs);
                GeneratedSyntaxTreeOpt = SyntaxTree.Create(_sourceName.AppendSuffixName("__G__"), generatedCompilationUnit);
            }
        }
    }
    public sealed class Namespace : Object
    {
        internal JsonTypeDeclarationTable JsonTypeDeclarationTable { get; private set; }
        public JsonTypeDeclarationTable.ReadOnly JsonTypeDeclarations { get { return JsonTypeDeclarationTable.AsReadOnly(); } }
        public NamespaceDeclarationSyntax OriginalNamespaceDeclaration { get; private set; }
        public NamespaceDeclarationSyntax GeneratedNamespaceDeclaration { get; private set; }
        public CompilationUnit ParentCompilationUnit { get { return (CompilationUnit)Parent; } }
        private string _namespaceDeclarationFullName;
        public string GetFullName(bool includeGlobalPrefix = true)
        {
            if (_namespaceDeclarationFullName == null)
                _namespaceDeclarationFullName = CSharpUtilities.GetNamespaceDeclarationFullName(OriginalNamespaceDeclaration);
            if (includeGlobalPrefix)
                return _namespaceDeclarationFullName;
            return _namespaceDeclarationFullName.StripGlobalPrefix();
        }
        internal Namespace(CompilationUnit parent, Node namespaceDeclarationNode, NamespaceDeclarationSyntax originalNamespaceDeclaration)
            : base(parent)
        {
            JsonTypeDeclarationTable = new JsonTypeDeclarationTable();
            OriginalNamespaceDeclaration = originalNamespaceDeclaration;
            Accept(namespaceDeclarationNode);
        }
        internal override void Accept(Node namespaceDeclarationNode)
        {
            base.Accept(namespaceDeclarationNode);
            foreach (var memberNode in namespaceDeclarationNode.ChildAsList("Members").Where(i => i.IsNotCSharpNode()))
            {
                JsonTypeDeclaration item;
                switch (memberNode.Label())
                {
                    case "JsonObjectDeclaration":
                        item = new JsonObjectDeclaration(this, memberNode);
                        break;
                    case "JsonArrayDeclaration":
                        item = new JsonArrayDeclaration(this, memberNode);
                        break;
                    default:
                        throw new ArgumentException();
                }
                JsonTypeDeclarationTable.AddOrThrow(item);
            }
        }
        internal override void Resolve()
        {
            base.Resolve();
            foreach (var i in JsonTypeDeclarationTable) i.Resolve();
        }
        internal override void Analyze()
        {
            base.Analyze();
            foreach (var i in JsonTypeDeclarationTable) i.Analyze();
        }
        internal override void Generate()
        {
            base.Generate();
            var classes = JsonTypeDeclarationTable.Select(i => { i.Generate(); return i.ClassDeclaration; });
            GeneratedNamespaceDeclaration = CSharpUtilities.CreateNamespaceDeclarationSyntax(GetFullName(false), usings: OriginalNamespaceDeclaration.Usings, members: classes,
            externs: OriginalNamespaceDeclaration.Externs);
        }
    }
    public abstract class JsonTypeDeclaration : Object
    {
        public Identifier Name { get; private set; }
        public ClassDeclarationSyntax ClassDeclaration { get; internal set; }
        internal JsonTypeDeclaration(Namespace parent) : base(parent) { }
        internal JsonTypeDeclaration(Namespace parent, Node node) : base(parent) { Accept(node); }
        internal override void Accept(Node node)
        {
            base.Accept(node);
            var classDeclarationNode = node.Child("ClassDeclaration");
            Name = new Identifier(classDeclarationNode.Child("Identifier"));
            ClassDeclaration = (ClassDeclarationSyntax)classDeclarationNode.ToSyntaxNode();
        }
    }
    public sealed class JsonTypeDeclarationTable : KeyedCollection<Identifier, JsonTypeDeclaration>
    {
        internal JsonTypeDeclarationTable() { }
        internal override Identifier GetKeyForItem(JsonTypeDeclaration item) { return item.Name; }
    }
    public sealed class JsonObjectDeclaration : JsonTypeDeclaration
    {
        internal JsonObjectMemberDeclarationTable JsonObjectMemberDeclarationTable { get; private set; }
        public JsonObjectMemberDeclarationTable.ReadOnly JsonObjectMemberDeclarations { get { return JsonObjectMemberDeclarationTable.AsReadOnly(); } }
        internal JsonObjectDeclaration(Namespace parent, Node node)
            : base(parent)
        {
            JsonObjectMemberDeclarationTable = new JsonObjectMemberDeclarationTable();
            Accept(node);
        }
        internal override void Accept(Node node)
        {
            base.Accept(node);
            foreach (var memberNode in node.Child("ClassDeclaration").ChildAsList("Members").Where(i => i.IsNotCSharpNode()))
            {
                JsonObjectMemberDeclaration item;
                switch (memberNode.Label())
                {
                    case "JsonObjectMemberDeclaration":
                        item = new JsonObjectMemberDeclaration(this, memberNode);
                        break;
                    default:
                        throw new ArgumentException();
                }
                JsonObjectMemberDeclarationTable.AddOrThrow(item);
            }
        }
        internal override void Resolve()
        {
            base.Resolve();
            foreach (var i in JsonObjectMemberDeclarationTable) i.Resolve();
        }
        internal override void Analyze()
        {
            base.Analyze();
            foreach (var i in JsonObjectMemberDeclarationTable) i.Analyze();
        }
        internal override void Generate()
        {
            base.Generate();
            var properties = JsonObjectMemberDeclarationTable.Select(i => { i.Generate(); return i.PropertyDeclaration; });
            ClassDeclaration = ClassDeclaration.Update(attributes: ClassDeclaration.Attributes, modifiers: ClassDeclaration.Modifiers, keyword: ClassDeclaration.Keyword,
                identifier: ClassDeclaration.Identifier, typeParameterListOpt: ClassDeclaration.TypeParameterListOpt, baseListOpt: ClassDeclaration.BaseListOpt,
                constraintClauses: ClassDeclaration.ConstraintClauses, openBraceToken: ClassDeclaration.OpenBraceToken,
                members: CSharpUtilities.CreateSyntaxList(ClassDeclaration.Members.Concat(properties)),
                closeBraceToken: ClassDeclaration.CloseBraceToken, semicolonTokenOpt: ClassDeclaration.SemicolonTokenOpt);
        }
    }
    public sealed class JsonObjectMemberDeclaration : Object
    {
        public Identifier Name { get; private set; }
        public TypeSyntax Type { get; private set; }
        public PropertyDeclarationSyntax PropertyDeclaration { get; private set; }
        internal JsonObjectMemberDeclaration(JsonObjectDeclaration parent, Node node) : base(parent) { Accept(node); }
        internal override void Accept(Node node)
        {
            base.Accept(node);
            Name = new Identifier(node.Child("Identifier"));
            Type = (TypeSyntax)node.Child("Type").ToSyntaxNode();
        }
        internal override void Generate()
        {
            base.Generate();
            PropertyDeclaration = Syntax.PropertyDeclaration(modifiers: CSharpUtilities.PublicModifier, type: Type, identifier: Name.CreateSyntaxToken(),
            accessorList: CSharpUtilities.CreateAccessorListSyntax(first: CSharpUtilities.CreatePropertyAccessorDeclarationSyntax(),
            second: CSharpUtilities.CreatePropertyAccessorDeclarationSyntax(getAccessor: false)));
        }
    }
    public sealed class JsonObjectMemberDeclarationTable : KeyedCollection<Identifier, JsonObjectMemberDeclaration>
    {
        internal JsonObjectMemberDeclarationTable() { }
        internal override Identifier GetKeyForItem(JsonObjectMemberDeclaration item) { return item.Name; }
    }
    public sealed class JsonArrayDeclaration : JsonTypeDeclaration
    {
        public FieldDeclarationSyntax ElementsFieldDeclaration { get; private set; }
        public PropertyDeclarationSyntax ElementsPropertyDeclaration { get; private set; }
        internal JsonArrayDeclaration(Namespace parent, Node node) : base(parent, node) { }
        internal override void Generate()
        {
            base.Generate();
            string elementTypeName = "object";
            if (ClassDeclaration.TypeParameterListOpt != null)
                foreach (var typeParameter in ClassDeclaration.TypeParameterListOpt.Parameters)
                {
                    var typeName = typeParameter.Identifier.ValueText;
                    if (Identifier.Equals(typeName, "TElement"))
                    {
                        elementTypeName = typeName;
                        break;
                    }
                }
            var fieldTypeName = string.Format(CultureInfo.InvariantCulture, @"global::System.Collections.Generic.List<{0}>", elementTypeName);
            var getAccessorBodyText = string.Format(CultureInfo.InvariantCulture, @"{{ if (__elements__ == null) __elements__ = new global::System.Collections.Generic.List<{0}>(); return __elements__; }}", elementTypeName);
            ElementsFieldDeclaration = CSharpUtilities.CreateFieldDeclarationSyntax(CSharpUtilities.PrivateModifier, fieldTypeName, "__elements__");
            ElementsPropertyDeclaration = CSharpUtilities.CreatePropertyDeclarationSyntax(CSharpUtilities.PublicModifier, fieldTypeName, "Elements",
            (BlockSyntax)Syntax.ParseStatement(getAccessorBodyText), false);
            ClassDeclaration = ClassDeclaration.Update(attributes: ClassDeclaration.Attributes, modifiers: ClassDeclaration.Modifiers, keyword: ClassDeclaration.Keyword,
                identifier: ClassDeclaration.Identifier, typeParameterListOpt: ClassDeclaration.TypeParameterListOpt, baseListOpt: ClassDeclaration.BaseListOpt,
                constraintClauses: ClassDeclaration.ConstraintClauses, openBraceToken: ClassDeclaration.OpenBraceToken,
                members: CSharpUtilities.CreateSyntaxList(ClassDeclaration.Members.Concat(new SyntaxNode[] { ElementsFieldDeclaration, ElementsPropertyDeclaration })),
                closeBraceToken: ClassDeclaration.CloseBraceToken, semicolonTokenOpt: ClassDeclaration.SemicolonTokenOpt);
        }
    }
}
